<?php

namespace App\Models;

use App\Http\Requests\User\PasswordResetRequest;
use Carbon\Carbon;
use Illuminate\Auth\Authenticatable;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Cache;
use DavinBao\LaravelXunSearch\Model\SearchableInterface;
use DavinBao\LaravelXunSearch\Model\SearchTrait;

use Kbwebs\MultiAuth\PasswordResets\CanResetPassword;
use Kbwebs\MultiAuth\PasswordResets\Contracts\CanResetPassword as CanResetPasswordContract;


class Admin extends Model implements AuthenticatableContract, CanResetPasswordContract
{
    use SoftDeletes,
        Authenticatable,
        SearchTrait,
        CanResetPassword,
        RolesTrait;

    protected $table = 'admins';
    protected $fillable = ['username', 'email', 'password', 'confirm_token', 'confirmed_at'];
    protected $hidden = ['password', 'remember_token'];

    /**
     * Base User query
     *
     * @param boolean $withTrashed Get with deleted
     * @param boolean $withJoin Use defined joins
     * @return Model
     */
    private static function base($withTrashed = false, $withJoin = false) {
        $query = self::select('admins.*')
            ->with('roles');

        $withTrashed ? $query->withTrashed() : null;

        if ($withJoin) {
            $query->leftJoin('admin_roles as ur', 'ur.admin_id', '=', 'admins.id')
                ->leftJoin('roles as r', 'r.id', '=', 'ur.role_id');
        }

        $query->distinct();

        return $query;
    }

    /**
     * Creates all elements query
     *
     * @param Boolean $withTrashed With soft deleted entries
     * @param Boolean $withJoin With join clauses
     * @return Model
     */
    public static function getAll($withTrashed, $withJoin) {
        $query = self::base($withTrashed, $withJoin);

        return $query;
    }

    /**
     * Get last seen
     *
     * @return String
     */
    public function lastSeen() {
        if (Cache::has('last_seen_' . $this->id)) {
            return Cache::get('last_seen_' . $this->id);
        } elseif ($this->last_seen) {
            return $this->last_seen;
        } else {
            return null;
        }
    }
    /**
     * Change user profile
     *
     * @param Request $request
     */
    public function changeProfile(Request $request) {
        $this->username = $request->input('username');

        if ($request->input('password')) {
            $this->password = Hash::make($request->input('password'));
        }

        $this->email = $request->input('email');
        $this->save();
    }

    /**
     * Change settings
     *
     * @param Request $request
     */
    public function changeSettings(Request $request) {
        if ($request->input('active')) {
            $this->confirmed_at = Carbon::now();
            $this->confirm_token = null;
        } else {
            $this->deleted_at = Carbon::now();
        }

        $this->save();
    }

    /**
     * Change avatar
     *
     * @param string $fileName
     */
    public function changeAvatar($fileName) {
        $this->avatar = $fileName;
        $this->save();
    }

    /**
     * Deletes avatar
     */
    public function deleteAvatar() {
        $this->avatar = null;
        $this->save();
    }

    /**
     * Roles relation
     *
     * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
     */
    public function roles() {
        return $this->belongsToMany('App\Models\Role', 'admin_roles');
    }

    /**
     * Handles user account confirmation
     *
     * @return Array
     * @internal param \App\Models\User $user
     */
    public function confirmRegistration() {
        $this->confirm_token = null;

        $this->confirmed_at = date('Y-m-d H:i:s');
        $this->save();

        $data = [
            'username' => $this->username,
            'user_email' => $this->email,
            'created_at' => $this->created_at,
            'confirmed_at' => $this->confirmed_at
        ];

        return $data;
    }

    /**
     * Gets a single admin
     *
     * @param int $id User id
     * @param boolean $withTrashed Extract with soft deleted
     * @param boolean $withJoins Extract record with joins
     * @return User
     */
    public static function getAdmin($id, $withTrashed = false, $withJoins = false) {
        $admin = self::base($withTrashed, $withJoins)
            ->where('id', $id)
            ->first();

        return $admin;
    }

    /**
     * Get all admin users
     *
     * @param boolean $withTrashed Add trashed elements
     * @param boolean $withJoin Add joins
     * @return Array
     * @internal param bool $with_thrashed Get with soft deleted
     */
    public static function getAdmins($withTrashed, $withJoin) {
        if (Cache::has('admin_users')) {
            return Cache::get('admin_users');
        } else {
            $query = self::base($withTrashed, $withJoin)
                ->where('r.role', 'admin')
                ->get();

            Cache::put('admin_users', $query, 60);

            return $query;
        }
    }

    /**
     * Handles search
     *
     * @param Array $search
     * @return self
     */
    public static function search($search) {
        $result = self::getsearch()->getIdList($search);

        $query = self::base(true, true)
            ->whereIn('admins.id', $result);

        return $query;
    }

    /**
     * Handles password changing on password reset
     *
     * @param \App\Http\Requests\Request|PasswordResetRequest $request
     */
    public static function changePassword(PasswordResetRequest $request) {
        $admin = self::where('email', $request->input('email'))->first();

        if(!is_null($admin)){
            $admin->password = Hash::make($request->input('password'));
            return $admin->save();
        }
        return false;
    }

    /**
     * Is the model available for search indexing?
     *
     * @return boolean
     */
    public function isSearchable()
    {
        return true;
    }

    /**
     * @inheritdoc
     */
    public static function searchableIds()
    {
        return self::all()->lists('id');
    }

    /**
     * Flush the users cache
     *
     * @param \App\Models\User $user
     */
    public static function flushCache(Admin $admin = null) {
        if ($admin && $admin->hasRole('admin')) {
            Cache::flush(['admin_users']);
        }
    }
}